import fileApi from "@/uni_modules/hbh-fileIo/js_sdk/index.js"
import {
	requestUrl
} from "@/common/config.js"
import SDTime from "silly-datetime";
import {
	addUserTask,
	queryUserTask,
	putUserTaskisSuccess,
	putUserTaskDownloadTime
} from "@/api/index.js"
import {
	splitTxtContent
} from "@/common/documentFilesplitContent.js"
export default {
	namespaced: true, //命名空间必须写
	state: {
		downTaskList: [], //下载任务队列,
		downThreadLoading:0,//正在开启的下载进程数量
		maxThread:1,//最运行大线程数
	},
	getters: {

	},
	//唯一修改state值的方法 
	// commit
	mutations: {
		//初始化同步
		initDownTask(state,arr){
			state.downTaskList=arr
			// console.log(state.downTaskList)
		},
		//同步改变任务队列
		realAdd(state, reciveVal) {
			state.downTaskList.push(reciveVal)
		},
		//修改state
		putStateDownList(state,{type,index,downingSize,totalSize,process}){
			switch (type){
				case 'addThread':
					state.downThreadLoading++
						break;
				case 'loseThread':
					state.downThreadLoading--
					// console.log(state.downThreadLoading)
						break;
				case 'start':
					state.downTaskList[index].isStart=true//是否开始下载
						break;
				case 'loading':
					state.downTaskList[index].downingSize=downingSize
					state.downTaskList[index].totalSize=totalSize
					state.downTaskList[index].process=parseInt(Number((downingSize /totalSize) *100))
						break;
				case 'fail':
					state.downTaskList[index].isdown=true//下载过了
					state.downTaskList[index].isStart=false//下载了不管失败与成功重置状态
					state.downTaskList[index].isDecompression=false//分割分章不管成功失败进入失败即重下
					state.downTaskList[index].downStatus=2//下载失败
						break;
				case 'success':
					state.downTaskList[index].isdown=true//下载过了
					state.downTaskList[index].isStart=false//下载了不管失败与成功重置状态
					state.downTaskList[index].isDecompression=true//分割分章成功
					state.downTaskList[index].downStatus=1//下完成功
						break;
				default:
					break;
			}
		}
	},
	// 异步的操作
	// dispatch
	actions: {
		//将小说简介数据保存到本地的txt文件里
		saveDescribeTOtxt({commit},downObj) {
			// 请求本地文件系统对象
			plus.io.requestFileSystem(
				plus.io.PUBLIC_DOCUMENTS, // 文件系统中的根目录
				fs => {
					// 创建或打开文件, fs.root是根目录操作对象,直接fs表示当前操作对象,同级会不生效，多加了层目录
					fs.root.getFile(`downloadTxt/${downObj.fileNameId}/describe/describe.txt`, {
						create: true // 文件不存在则创建
					}, fileEntry => {
						// 文件在手机中的路径
						fileEntry.createWriter(writer => {
							// 写入文件成功完成的回调函数
							writer.onwrite = e => {
								console.log("describe.txt写入数据成功");
							};
							// 写入数据
							writer.write(downObj.descrie);
						})
					}, e => {
						console.log("getFile failed: " + e.message);
					});
				},
				e => {
					console.log(e.message);
				}
			);
		},
		//将base64图片数据保存到本地的txt文件里
		saveJpgTOtxt({commit},downObj) {
			// 请求本地文件系统对象
			plus.io.requestFileSystem(
				plus.io.PUBLIC_DOCUMENTS, // 文件系统中的根目录
				fs => {
					// 创建或打开文件, fs.root是根目录操作对象,直接fs表示当前操作对象
					fs.root.getFile(`downloadTxt/${downObj.fileNameId}/base64/${downObj.author}@@${downObj.total}.txt`, {
						create: true // 文件不存在则创建
					}, fileEntry => {
						// 文件在手机中的路径
						fileEntry.createWriter(writer => {
							// 写入文件成功完成的回调函数
							writer.onwrite = e => {
								console.log("picture.txt写入数据成功");
								//再次将描述内容也写入一个txt文件里
							};
							// 写入数据
							writer.write(downObj.txtPicture);
						})
					}, e => {
						console.log("getFile failed: " + e.message);
					});
				},
				e => {
					console.log(e.message);
				}
			);
		},
		//初始化
		initDownTaskSync({
			commit
		}){
			//调接口查询历史下载任务记录
			queryUserTask().then(async(res)=>{
				if(res.code==200 && Array.isArray(res.data)){
					//归类
					let grouped=res.data.reduce((prev,cur)=>{
						if(!prev[cur.fileNameId]){
							prev[cur.fileNameId]=[]
						}
						prev[cur.fileNameId].push(cur)
						return prev
					},{})
					//过滤
					for(let key in grouped){
						grouped[key].forEach((item)=>{
							item.isdown =item.downStatus==3?false:true //标记小说是否在下载队列
							item.isDecompression = false //标记小说下载完后是否解压分割了
							item.downStatus=item.downStatus//1：成功,2:失败,3:未开始下载(默认)
							item.isStop=false//是否暂停下载
							item.downingSize=0//初始下载量大小
							item.totalSize=0//初始总大小
							item.process=0//初始下载进度
							item.isStart=false//是否开始下载
							item.isSign=grouped[key].length>1?true:false//下载过本地被删除
						})
						if(grouped[key].length>1){
							let noTime=grouped[key].filter(item=>item.downStatus!=1)
							let residue=grouped[key].filter(item=>item.downStatus==1)
							residue=residue.sort((a,b)=>Date.parse(b.download_time)-Date.parse(a.download_time))
							// console.log(residue)
							const isExist = await fileApi.fileIsExist(
							`downloadTxt/${residue[0].fileNameId}/${residue[0].bookName+'.txt'}`
							)
							if (isExist) {
								residue[0].isSign=false
							}
							grouped[key]=noTime.concat(residue)
						}else{
							
						}
					}
					let newArr=[]
					Object.keys(grouped).forEach(key=>{
						const values=grouped[key]
						values.forEach(item=>newArr.push(item))
					})
					//扁平化
					commit("initDownTask",newArr)
				}
			}).catch((err)=>{
				console.log(err)
			})
		},
		//添加
		async	add({
			commit,
			state,
			dispatch
		}, reciveVal) { //不开启严格模式，actions可以修改state,但为了避免出现意外，遵守官方规则
			try{
				const res=await addUserTask({
					fileNameId:reciveVal.fileNameId,
					bookName:reciveVal.bookName
				})
				reciveVal.task_id=res.data.task_id
				commit("realAdd", reciveVal)
			}catch(e){
				//TODO handle the exception
			}
			dispatch("goodControl")
			
		},
		//合适时机开启控制
		goodControl({
			commit,
			state,
			dispatch
		}){
			if(state.downThreadLoading>=state.maxThread){
				console.log("超过最大同时下载数，已加入排队列表!")
				return
			}
			commit("putStateDownList",{type:'addThread'})//添加一个下载线程
			//直接开启下载
			dispatch("startDown")
		},
		//开启下载
		startDown({
			commit,
			state,
			dispatch
		}) {
			//寻找优先级最高的下载,排除暂停任务
			//更改方式为寻找下标findIndex
			let currentDownIndex=state.downTaskList.findIndex(item=>item.isStop==false&&item.downStatus==3&&item.isStart==false)

			if(currentDownIndex==-1){//没有可执行下载文件了就停止吧,不能超过三个下载线程,这思路错了，本质还是要自动下载兄弟
			//还需要将所有线程数递减
				commit("putStateDownList",{type:'loseThread'})//删除一个下载线程
				console.log("全部任务已完成！")
				return
			}
			commit("putStateDownList",{type:'start',index:currentDownIndex})//初始修改state的状态
			
			//从第一个满足条件的开始
			let downObj =state.downTaskList[currentDownIndex]
			//真正的下载
			dispatch("downRealObj", {...downObj,index:currentDownIndex}).then((res) => { //下载成功
				putUserTaskisSuccess({
					task_id:downObj.task_id,
					downStatus:1
				}).then((res)=>{
					console.log(res,"--------")
				})
				// console.log(res)
				commit("putStateDownList",{type:'success',index:currentDownIndex})//修改state的状态
				dispatch("startDown")//成功后自动递归
			}).catch((err) => { //下载失败,删除目录和文件
				// console.log(err)
				putUserTaskisSuccess({
					task_id:downObj.task_id,
					downStatus:2
				}).then((res)=>{
					console.log(res,"--------")
				})
				commit("putStateDownList",{type:'fail',index:currentDownIndex})//修改state的状态
				dispatch("startDown")//失败后自动递归
				plus.io.resolveLocalFileSystemURL(fileApi.golabelUrl, (entry) => {
					entry.getDirectory(
						`documents/downloadTxt/${downObj.fileNameId}`, {
							create: true, //目录不存在就会自动递归创建
							exclusive: false //反向标记，其本身没有任何效果，需与create属性值设置为true时一起使用
						}, (dir) => {
							var directoryReader = dir.createReader();
							//读取这个目录下的所有文件
							directoryReader.readEntries((entries) => {
								if (entries.length >
									0) { //删除所有子文件和子目录
									entries.forEach((item,
										index
									) => {
										item.remove()
									})
									//删除当前目录
									dir.remove()
								}
							}, (e) => {
								console.log(
									"获取当目录下所有文件和子目录失败！"
								)
								//删除当前目录
								dir.remove()
							})
				
						}, (e) => {
							console.log(e)
						})
				}, (err) => { //路径不存在或文件不存在
				console.log(err)
				});
			})
		},
		//创建下载任务
		createDownTask({
			commit,
			dispatch,
			state
		}, downObj) {
			return new Promise((resolve, reject) => {
				//配置下载任务参数
				let options = {

					//自定义下载文件路径，保存文件路径仅支持以"_downloads/"、"_doc/"、"_documents/"开头的字符串

					filename: `_documents/downloadTxt/${downObj.fileNameId}/`,

					//默认为GET请求。注意这里需大写“GET”、“POST”

					method: 'POST',
					timeout: 3,
					retry: 1,
					retryInterval: 5,
					data: JSON
						.stringify({
							fileNameId: downObj
								.fileNameId,
						})
				}
				let dtask = plus.downloader
					.createDownload(
						`${requestUrl}/downTxtNovel`,
						options,
						(download,
							status) => {
							if (status ==
								200) {
								console
									.log(
										"下载完成"
									)
								resolve
									(
										88)
										dtask.clear()
										dtask=null
							} else {
								console
									.log(
										"下载失败"
									)
									// setTimeout(async()=>{
									// 	const hres = await fileApi.delDirectory('documents/downloadTxt/' + downObj.fileNameId)
									// 	// fileApi.delDirectory('documents/downloadTxt/'+downObj.fileNameId).then((res)=>{
									// 		console.log(hres)
									// },10000)
								
								// }).catch((err)=>{
								// 	console.log(err)
								// })
								reject
									(
										99)
								dtask.clear()
								dtask=null
							}
						}
					)
				//设置请求头信息，token携带
				dtask.setRequestHeader(
					"Authorization",
					'Bearer ' + uni
					.getStorageSync(
						"TOKEN")
				) //post请求，需要自定义header里一些字段，携带token啥的
				dtask.addEventListener(
					'statechanged', (
						task) => {

						if (!
							dtask) {
							return;
						}
						switch (task
							.state
						) {
							case undefined:
								console
									.log(
										'下载任务未开始');
								break;

							case 0:
								console
									.log(
										'下载任务开始调度');
								break;
							case 1:
								console
									.log(
										'下载任务开始请求');
								break;
							case 2:
								console
									.log(
										'下载任务网络连接已建立，服务器返回响应，准备传输数据内容'
									);
								//这里可以弹出下载进度框了
								//更新下载时间
								putUserTaskDownloadTime({
									task_id:downObj.task_id
								})
								break;
							case 3:
								commit("putStateDownList",{type:'loading',
									index:downObj.index,
									downingSize:(task.downloadedSize /1024 /1024).toFixed(2),
									totalSize:(task.totalSize /1024 / 1024).toFixed(2)
								})//初始修改state的状态
								break;
							case 4:
								cnosole
									.log(
										'下载任务已完成');

								break;
							case 5:
								cnosole
									.log(
										'下载任务已暂停');

								break;

						}

					});

				// 开始下载

				dtask.start()
			})
		},
		//下载
		downRealObj({
			commit,
			dispatch,
			state
		}, downObj) {
			return new Promise((resolve, reject) => {
				plus.io.resolveLocalFileSystemURL(fileApi.golabelUrl, (entry) => {
					entry.getDirectory(
						`documents/downloadTxt/${downObj.fileNameId}`, {
							create: true, //目录不存在就会自动递归创建
							exclusive: false //反向标记，其本身没有任何效果，需与create属性值设置为true时一起使用
						}, (dir) => {
							var directoryReader = dir.createReader();
							//读取这个目录下的所有文件
							directoryReader.readEntries((entries) => {
								if (entries.length >
									0) { //删除所有子文件和子目录
									entries.forEach((item,
										index
									) => {
										item.remove()
									})
									//删除当前目录
									dir.remove()
								}
								dispatch('saveJpgTOtxt',downObj)
								dispatch('saveDescribeTOtxt',downObj)
								//干净了往下执行,那就先下载,创建下载任务
								dispatch('createDownTask',
									downObj).then(async(
									res
									) => { //下载成功！
									//读取小说内容进行切割加快渲染速度
									try{
										const result = await fileApi.getFileList(
											`documents/downloadTxt/${downObj.fileNameId}`
										)
										if(result.code==200){
											//找到文件后缀为.txt的
											let fileName=result.data.filter(item=>item.name.match(/.txt/g)!=null).map(item=>item.name)[0]
											console.log(fileName)
											const novelRes = await fileApi.getFileData(
												`downloadTxt/${downObj.fileNameId}/${fileName}`
											)
											if(novelRes.code==200){//切割中
												const novelSplit=await	splitTxtContent(novelRes.result,downObj.fileNameId)
												if(novelSplit.code==200){
													resolve('OK')
												}else{
													reject('小说切割失败')
												}
												
											}else{
												reject('读取小说内容失败')
											}
										}else{
											reject('读取目录失败')
										}
										
									}catch(e){
										//TODO handle the exception
										reject(e)
									}
								}).catch(async(err) => { //下载失败
									await	fileApi.delDirectory('documents/downloadTxt/'+downObj.fileNameId)
									directoryReader.remove()
									reject(err)
								})

							}, (e) => {
								console.log(
									"获取当目录下所有文件和子目录失败！"
								)
								reject(e)
							})

						}, (e) => {
							console.log(e)
							reject(e)
					})
				}, (err) => { //路径不存在或文件不存在
					reject(err)
				});
			})
		}

	}
}